<?php

namespace App\Jobs;

use App\Events\RefreshUserInfo;
use App\Models\AfterSaleOrder;
use App\Models\Agent;
use App\Models\AgentRevenue;
use App\Models\AgentReward;
use App\Models\AgentRewardRuleSettings;
use App\Models\CommodityActivityStatistics;
use App\Models\DailyReportStatistics;
use App\Models\Order;
use App\Models\SummaryBase;
use App\Services\CacheLockKeyConst;
use Carbon\Carbon;
use Carbon\CarbonInterface;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Queue\SerializableClosure;
use Illuminate\Support\Str;

/**
 * 撤销订单
 * Class AfterSaleStatisticsJob
 * @package App\Jobs
 */
class CancelSkuOperationStatisticsJob extends Job
{
    /** @var Order */
    private $order;

    /** @var CarbonInterface */
    private $orderCreatedAt;

    /** @var Agent */
    private $agent;

    private $agentSnapshot;

    /** @var Agent */
    private $directInviter;

    private $directInviterSnapshot;

    /** @var Agent */
    private $indirectInviter;

    private $indirectInviterSnapshot;

    /**
     * @var int 要撤回的 sku 对应的订单
     */
    private $orderId;

    /**
     * @var array 要撤回的 sku 以及对应的数量
     */
    private $skuWithQuantity;

    /**
     * @var bool 是否取消订单操作
     */
    private $isCancelOrder;

    /**
     * @var bool 订单是否已失效
     */
    private $isOrderInvalid = true;

    /**
     * @var bool 需要扣减订单
     */
    private $needDeductionOrder;

    /**
     * sku 统计的 model
     * @var array
     */
    private $commodityActivitySkuStatistics = [];

    /**
     * @var SerializableClosure 完成后的回调
     */
    private $successFun;

    /**
     * @var SerializableClosure 失败后的回调
     */
    private $errorFun;

    /**
     * @var SerializableClosure 商品活动 SKU 统计方法
     */
    private $commodityActivitySkuStatisticsFun;

    public function __construct($skuWithQuantity, $orderId, $isCancelOrder = false, SerializableClosure $commodityActivitySkuStatisticsFun = null, SerializableClosure $successFun = null, SerializableClosure $errorFun = null)
    {
        $this->skuWithQuantity = $skuWithQuantity;
        $this->orderId = $orderId;
        $this->isCancelOrder = $isCancelOrder;
        $this->commodityActivitySkuStatisticsFun = $commodityActivitySkuStatisticsFun;
        $this->successFun = $successFun;
        $this->errorFun = $errorFun;
    }

    public function handle()
    {
        try {
            // 整理初始化数据
            $this->order = Order::query()->with([
                'agent', 'directInviter', 'indirectInviter',
                'afterSaleOrder' => function (HasMany $query) {
                    $query
                        ->with(['afterSaleOrderSkus'])
                        ->where('status', AfterSaleOrder::STATUS_PASSED)
                        ->whereIn('type', [AfterSaleOrder::TYPE_RETURN, AfterSaleOrder::TYPE_REFUND_ONLY]);
                },
                'skus' => function (HasMany $query) {
                    $query->with(['commodityActivitySku']);
                }
            ])->findOrFail($this->orderId);
            $this->orderCreatedAt = Carbon::parse($this->order['created_at']);
            $this->agent = $this->order->agent;
            $this->agentSnapshot = $this->order->agent_snapshot;

            $this->directInviter = $this->order->directInviter;
            $this->directInviterSnapshot = $this->order->direct_inviter_snapshot;
            $this->indirectInviter = $this->order->indirectInviter;
            $this->indirectInviterSnapshot = $this->order->indirect_inviter_snapshot;

            // 解决 firstOrCreate 并发问题, 先创建 (售后理论上不需要,因为在下订单的时候就已经创建了)
            // [统计] 每日报表
            /** @var DailyReportStatistics $dailyReportStatistics */
            $dailyReportStatistics = CacheLockKeyConst::dailyReportStatistics($this->orderCreatedAt);
            // [统计] 活动 SKU
            $this->order->skus->each(fn($orderSku) => $this->commodityActivitySkuStatistics[$orderSku['commodity_activity_sku_id']] = CacheLockKeyConst::commodityActivitySkuStatistics(
                $orderSku['commodity_activity_sku_id'], $this->order['commodity_id'], $this->order['commodity_activity_id']));
            // [统计] 活动
            /** @var CommodityActivityStatistics $commodityActivityStatistics */
            $commodityActivityStatistics = CacheLockKeyConst::commodityActivityStatistics($this->order['commodity_id'], $this->order['commodity_activity_id']);

            $this->isOrderInvalid = $this->isOrderRetired(); // 订单 退完了, 订单失效
            $this->needDeductionOrder = $this->isCancelOrder || $this->isOrderInvalid; // 是否需要扣减订单数量 (是取消订单 或者 退完了)

            \DB::beginTransaction();

            $directInviterReward = []; // 直接邀请奖励
            $indirectInviterReward = []; // 间接邀请奖励
            $levelGradeDifference = []; // 层级差价
            $calculationLevelGradeDifferenceFun = function ($submitAmount, $skuSnapShot, $superior, $subordinate, &$levelGradeDifference) {
                $unitPrice = abs($skuSnapShot[$subordinate . '_price'] - $skuSnapShot[$superior . '_price']); // 层级差价 (单价) ['strongman']['elite'] 大咖 => 精英 的差价
                $singleTotalPrice = $unitPrice * $submitAmount; // 单次 sku 总额
                $levelGradeDifference[$superior][$subordinate]['total'] = ($levelGradeDifference[$superior][$subordinate]['total'] ?? 0) + $singleTotalPrice; // 差价 * sku 数量 = 层级差价所有 sku 加起来的总额
                $levelGradeDifference[$superior][$subordinate]['sku_details'][$skuSnapShot['id']] = [
                    'quantity' => $submitAmount, // sku_id 对应 order sku 数量
                    'total' => $singleTotalPrice, // sku_id 对应 总额
                    'unit_price' => $unitPrice,
                ];
            };
            $skuTotalAmount = 0; // 根据实际退减 SKU 来算
            $totalIncome = 0; // 实际 SKU 相关收入
            $orderCommodityBalancePaid = $this->order->commodity_balance_paid; // 订单商品支付了的可提现金额
            $orderCommodityUnextractableBalancePaid = $this->order->commodity_unextractable_balance_paid; // 订单商品支付了的不可提现金额
            $commodityRevokeBalance = 0; // 商品撤回可提现金额
            $commodityRevokeUnextractableBalance = 0; // 商品撤回可提现金额
            foreach ($this->order->skus->filter(
            // 找到提交的 sku 对应数据
                fn($sku) => array_key_exists((int) $sku['commodity_activity_sku_id'], $this->skuWithQuantity)) as $orderSku) {

                $skuSnapShot = $orderSku['sku_snapshot']; // commodity_activity_sku 快照
                $submitAmount = $this->skuWithQuantity[$orderSku['commodity_activity_sku_id']]; // 提交的 sku 数量

                // 注意这里的结构和 $calculationLevelGradeDifferenceFun 方法内 $levelGradeDifference 的结构一致, 在 invitationReward 方法内用到
                $directInviterSingleSkuTotalReward = $submitAmount * $skuSnapShot['direct_invitation'];
                $directInviterReward['total'] = ($directInviterReward['total'] ?? 0) + $directInviterSingleSkuTotalReward; // 直接邀请 所有 sku 奖励总和
                $directInviterReward['sku_details'][$orderSku['commodity_activity_sku_id']] = ['quantity' => $submitAmount, 'total' => $directInviterSingleSkuTotalReward, 'unit_price' => $skuSnapShot['direct_invitation']]; // 直接邀请 单独 sku 奖励和

                $indirectInviterSingleSkuTotalReward = $submitAmount * $skuSnapShot['indirect_invitation'];
                $indirectInviterReward['total'] = ($indirectInviterReward['total'] ?? 0) + $indirectInviterSingleSkuTotalReward; // 间接邀请 所有 sku 奖励总和
                $indirectInviterReward['sku_details'][$orderSku['commodity_activity_sku_id']] = ['quantity' => $submitAmount, 'total' => $indirectInviterSingleSkuTotalReward, 'unit_price' => $skuSnapShot['indirect_invitation'],]; // 间接邀请 单独 sku 奖励和

                // 层级差价计算
                $calculationLevelGradeDifferenceFun($submitAmount, $skuSnapShot, 'strongman', 'elite', $levelGradeDifference);
                $calculationLevelGradeDifferenceFun($submitAmount, $skuSnapShot, 'strongman', 'group_owner', $levelGradeDifference);
                $calculationLevelGradeDifferenceFun($submitAmount, $skuSnapShot, 'elite', 'group_owner', $levelGradeDifference);

                // [统计] 商品 sku 维度相关数据
                if ($this->isCancelOrder) {
                    // 取消 才扣销量等等, 退货 退款 另外记录
                    $this->commodityActivitySkuStatistics[$orderSku['commodity_activity_sku_id']]->incrementOrDecrementQuantitySold($skuSnapShot['purchase_price'], $submitAmount, 'decrement'); // - 销量 和 总成本金额
                }
                $this->commodityActivitySkuStatistics[$orderSku['commodity_activity_sku_id']]->{'incrementOrDecrement' . Str::studly(Agent::LEVEL_MAP[$this->agentSnapshot['level']]['id']) . 'Shipments'}($orderSku['unit_price'], $skuSnapShot['purchase_price'], $submitAmount, 'decrement'); // - 当前代理商级别出货量 和 总金额 还有 总成本
                // 自定义 商品 sku 统计
                $this->commodityActivitySkuStatisticsFun !== null && $this->commodityActivitySkuStatisticsFun->getClosure()($this->commodityActivitySkuStatistics[$orderSku['commodity_activity_sku_id']], $skuSnapShot['purchase_price'], $submitAmount);

                $totalIncome += (($incomeTemp = $skuSnapShot['external_guide_price'] - $orderSku['unit_price']) < 0 ? 0 : $incomeTemp) * $submitAmount; // 当前代理商收入
                $commodityAmount = $orderSku['unit_price'] * $submitAmount; // 商品金额
                $skuTotalAmount += $commodityAmount; // 累加商品金额

                // 计算根据商品应返的 可提现金额 和 不可提现金额
                try {
                    [$commodityBalanceTemp, $commodityUnextractableBalanceTemp] = Agent::deductionBalance($commodityAmount, $orderCommodityBalancePaid, $orderCommodityUnextractableBalancePaid);
                    $commodityRevokeBalance += $commodityBalanceTemp;
                    $commodityRevokeUnextractableBalance += $commodityUnextractableBalanceTemp;
                } catch (\Exception $e) {
                    \Log::error('撤回的商品金额超出订单已支付的金额');
                }

                // 如果是取消,返还库存
                $this->isCancelOrder && $orderSku->commodityActivitySku->incrementStockAndDecrementSales($submitAmount);
            }

            // 返还用户金额
            $commodityRevokeBalance > 0 && $this->agent->incrementOrDecrementBalance($commodityRevokeBalance, $this->isCancelOrder ? AgentRevenue::TYPE_CANCEL_ORDER : AgentRevenue::TYPE_REFUND, $this->order);
            $commodityRevokeUnextractableBalance > 0 && $this->agent->incrementOrDecrementUnextractableBalance($commodityRevokeUnextractableBalance, $this->isCancelOrder ? AgentRevenue::TYPE_CANCEL_ORDER_UNEXTRACTABLE : AgentRevenue::TYPE_REFUND_UNEXTRACTABLE, $this->order);

            // 当前代理商业绩扣减
            if ($this->isCancelOrder) {
                $skuTotalAmount += $this->order->freight; // 运费 取消订单的时候会有用到,售后的退运费不在这范围内
            }
            $this->agentIncomeAccumulate($totalIncome, $skuTotalAmount);
            // 直接邀请 和 间接邀请
            $this->invitationReward($directInviterReward, $indirectInviterReward, $levelGradeDifference, $totalIncome, $skuTotalAmount, $commodityActivityStatistics);

            // 每日下单奖励
            $this->whetherToReachTheDailyReward();
            // 每月下单奖励
            $this->whetherToReachTheMonthlyReward();

            // 每日报表统计 订单总数 订单总金额
            $dailyReportStatistics->incrementOrDecrementOrderRelated($skuTotalAmount, 'decrement', $this->isOrderInvalid ? 1 : 0);

            // 更新订单数据,统计用到,具体数据根据 order sku 和 after order 来计算
            $this->order->update([
                'is_expired' => $this->isOrderInvalid ? Order::IS_EXPIRED_TRUE : Order::IS_EXPIRED_FALSE, // 订单失效 ?
                'total_amount' => \DB::raw('total_amount - ' . $skuTotalAmount),
                'commodity_price' => \DB::raw('commodity_price - ' . ($commodityRevokeBalance + $commodityRevokeUnextractableBalance)),
                'commodity_balance_paid' => \DB::raw('commodity_balance_paid - ' . $commodityRevokeBalance),
                'commodity_unextractable_balance_paid' => \DB::raw('commodity_unextractable_balance_paid - ' . $commodityRevokeUnextractableBalance),
                'commodity_amount' => \DB::raw('commodity_amount - ' . array_sum(array_values($this->skuWithQuantity))),
                'income' => \DB::raw('income - ' . $totalIncome)
            ]);

            // 最后的钩子
            $this->successFun !== null && $this->successFun->getClosure()($this->order);

            // 通知客户端刷新信息
            event(new RefreshUserInfo($this->agent->getKey()));

            \DB::commit();
        } catch (\Exception $e) {
            \Log::error(sprintf('撤销 JOB 出错: %s (%s[%d]); trace: %s', $e->getMessage(), $e->getFile(), $e->getLine(), $e->getTraceAsString()));
            \DB::rollBack();

            try {
                $this->errorFun !== null && $this->errorFun->getClosure()($this->order);
            } catch (\Exception $e) {
                \Log::error(sprintf('Error Callback 处理错误: %s (%s[%d]); trace: %s', $e->getMessage(), $e->getFile(), $e->getLine(), $e->getTraceAsString()));
            }

            throw $e;
        }
    }

    /**
     * 当前代理商业绩累加
     * @param $orderAmount
     */
    private function agentIncomeAccumulate($income, $orderAmount, $method = 'decrement'): void
    {
        // 累计收入
        $this->agent->incrementOrDecrementIncome($income, $method, $this->orderCreatedAt);
        // 自己业绩
        $this->agent->incrementOrDecrementPerformanceByOrder($orderAmount, $method, $this->orderCreatedAt, $this->needDeductionOrder ? 1 : 0); // 订单失效的情况下,扣减订单数
    }

    /**
     * 每日下单奖励
     */
    private function whetherToReachTheDailyReward(): void
    {
        $orderCreatedAtDay = $this->orderCreatedAt->format('Y-m-d'); // 下单日
        $dailySummary = $this->agent->dailySummary()->where(['day' => $orderCreatedAtDay, 'type' => SummaryBase::TYPE_AGENT])->first(); // 当日业绩统计

        // 当日拿到过的奖励
        /** @var Collection $theRewardGotToday */
        $theRewardGotToday = $this->agent
            ->rewards()
            ->where('type', AgentRewardRuleSettings::TYPE_DAILY_ORDER_REWARD)
            ->where('award_date', $orderCreatedAtDay)
            ->effective() // 有效的
            ->get();
        if ($theRewardGotToday->isNotEmpty()) {
            // 找出后来不满足的那些奖励
            /** @var AgentReward $rewardToday */
            foreach ($theRewardGotToday->filter(fn($reward) => ($dailySummary->performance_summary < $reward['threshold_amount'])) as $rewardToday) {
                if ($rewardToday['status'] === AgentReward::STATUS_PENDING_REVIEW) {
                    // 待审核的情况下 撤销
                    $rewardToday->update(['status' => AgentReward::STATUS_REVOKED]);
                } elseif ($rewardToday['status'] === AgentReward::STATUS_PASSED) {
                    // 已通过的情况下 追回
                    $this->agent->incrementOrDecrementBalance($rewardToday['reward'], AgentRevenue::TYPE_REVOCATION_DAILY_ORDER_REWARD, $this->order, 'decrment', $this->orderCreatedAt);
                    $rewardToday->update(['status' => AgentReward::STATUS_RECOVERED]);
                }
            }
        }
    }

    /**
     * 每月下单奖励
     */
    private function whetherToReachTheMonthlyReward(): void
    {
        $monthlySummary = $this->agent->monthlySummary()->where(['month' => (int) $this->orderCreatedAt->format('Ym'), 'type' => SummaryBase::TYPE_AGENT])->first(); // 当月业绩统计

        // 当月拿到过的奖励
        /** @var Collection $theRewardGotMonth */
        $theRewardGotMonth = $this->agent
            ->rewards()
            ->where('type', AgentRewardRuleSettings::TYPE_MONTHLY_ORDER_REWARD)
            ->whereBetween('award_date', [
                (clone $this->orderCreatedAt)->startOfMonth()->format('Y-m-d'),
                (clone $this->orderCreatedAt)->endOfMonth()->format('Y-m-d')
            ])
            ->effective() // 有效的
            ->get();
        if ($theRewardGotMonth->isNotEmpty()) {
            // 找出后来不满足的那些奖励
            /** @var AgentReward $rewardMonth */
            foreach ($theRewardGotMonth->filter(fn($reward) => ($monthlySummary->performance_summary < $reward['threshold_amount'])) as $rewardMonth) {
                if ($rewardMonth['status'] === AgentReward::STATUS_PENDING_REVIEW) {
                    // 待审核的情况下 撤销
                    $rewardMonth->update(['status' => AgentReward::STATUS_REVOKED]);
                } elseif ($rewardMonth['status'] === AgentReward::STATUS_PASSED) {
                    // 已通过的情况下 追回
                    $this->agent->incrementOrDecrementBalance($rewardMonth['reward'], AgentRevenue::TYPE_REVOCATION_ORDER_REWARD_PER_MONTH, $this->order, 'decrment', $this->orderCreatedAt);
                    $rewardMonth->update(['status' => AgentReward::STATUS_RECOVERED]);
                }
            }
        }
    }

    /**
     * 直接/间接 邀请奖励
     * @param $directInviterReward
     * @param $indirectInviterReward
     * @param $levelGradeDifference
     * @param $totalIncome
     * @param $orderAmount
     * @param $commodityActivityStatistics
     * @param string $method
     */
    private function invitationReward($directInviterReward, $indirectInviterReward, $levelGradeDifference, $totalIncome, $orderAmount, $commodityActivityStatistics, $method = 'decrement'): void
    {
        // 如果是取消操作, 撤销类型, 如果不是取消操作, 则是 退款退货撤销类型
        $revocationDirectInvitationReward = $this->isCancelOrder ? AgentRevenue::TYPE_REVOCATION_DIRECT_INVITATION_REWARD : AgentRevenue::TYPE_REFUND_REVOCATION_DIRECT_INVITATION_REWARD; // 直接邀请
        $revocationIndirectInvitationReward = $this->isCancelOrder ? AgentRevenue::TYPE_REVOCATION_INDIRECT_INVITATION_REWARD : AgentRevenue::TYPE_REFUND_REVOCATION_INDIRECT_INVITATION_REWARD; // 间接邀请
        $typeRevocationCommission = $this->isCancelOrder ? AgentRevenue::TYPE_REVOCATION_COMMISSION : AgentRevenue::TYPE_REFUND_REVOCATION_COMMISSION; // 佣金

        $levelGradeDifferenceReward = [
            Agent::LEVEL_GROUP_OWNER => [ // 第一层为 当前用户等级
                Agent::LEVEL_GROUP_OWNER => [ // 第二层为 直接邀请人奖励
                    'amount' => $directInviterReward,
                    'type' => $revocationDirectInvitationReward,
                    'indirect' => [ // 第二层为 间接邀请人奖励
                        Agent::LEVEL_GROUP_OWNER => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                        // 这里的 from to 是 amount 内 $levelGradeDifference 后的两个 key (级别) 前后顺序, 因为是无规律的所以单独再定义
                        Agent::LEVEL_ELITE => ['amount' => $levelGradeDifference['elite']['group_owner'], 'type' => $typeRevocationCommission, 'from' => 'elite', 'to' => 'group_owner'],
                        Agent::LEVEL_STRONGMAN => ['amount' => $levelGradeDifference['strongman']['group_owner'], 'type' => $typeRevocationCommission, 'from' => 'strongman', 'to' => 'group_owner'],
                    ]
                ],
                Agent::LEVEL_ELITE => [
                    'amount' => $levelGradeDifference['elite']['group_owner'],
                    'type' => $typeRevocationCommission,
                    'from' => 'elite',
                    'to' => 'group_owner',
                    'indirect' => [
                        Agent::LEVEL_GROUP_OWNER => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                        Agent::LEVEL_ELITE => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                        Agent::LEVEL_STRONGMAN => ['amount' => $levelGradeDifference['strongman']['elite'], 'type' => $typeRevocationCommission, 'from' => 'strongman', 'to' => 'elite'],
                    ]
                ],
                Agent::LEVEL_STRONGMAN => [
                    'amount' => $levelGradeDifference['strongman']['group_owner'],
                    'type' => $typeRevocationCommission,
                    'from' => 'strongman',
                    'to' => 'group_owner',
                    'indirect' => [
                        Agent::LEVEL_GROUP_OWNER => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                        Agent::LEVEL_ELITE => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                        Agent::LEVEL_STRONGMAN => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                    ]
                ]
            ],
            Agent::LEVEL_ELITE => [
                Agent::LEVEL_GROUP_OWNER => [
                    'amount' => $directInviterReward,
                    'type' => $revocationDirectInvitationReward,
                    'indirect' => [
                        Agent::LEVEL_GROUP_OWNER => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                        Agent::LEVEL_ELITE => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                        Agent::LEVEL_STRONGMAN => ['amount' => $levelGradeDifference['strongman']['elite'], 'type' => $typeRevocationCommission, 'from' => 'strongman', 'to' => 'elite'],
                    ]
                ],
                Agent::LEVEL_ELITE => [
                    'amount' => $directInviterReward,
                    'type' => $revocationDirectInvitationReward,
                    'indirect' => [
                        Agent::LEVEL_GROUP_OWNER => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                        Agent::LEVEL_ELITE => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                        Agent::LEVEL_STRONGMAN => ['amount' => $levelGradeDifference['strongman']['elite'], 'type' => $typeRevocationCommission, 'from' => 'strongman', 'to' => 'elite'],
                    ]
                ],
                Agent::LEVEL_STRONGMAN => [
                    'amount' => $levelGradeDifference['strongman']['elite'],
                    'type' => $typeRevocationCommission,
                    'from' => 'strongman',
                    'to' => 'elite',
                    'indirect' => [
                        Agent::LEVEL_GROUP_OWNER => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                        Agent::LEVEL_ELITE => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                        Agent::LEVEL_STRONGMAN => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                    ]
                ]
            ],
            Agent::LEVEL_STRONGMAN => [
                Agent::LEVEL_GROUP_OWNER => [
                    'amount' => $directInviterReward,
                    'type' => $revocationDirectInvitationReward,
                    'indirect' => [
                        Agent::LEVEL_GROUP_OWNER => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                        Agent::LEVEL_ELITE => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                        Agent::LEVEL_STRONGMAN => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                    ]
                ],
                Agent::LEVEL_ELITE => [
                    'amount' => $directInviterReward,
                    'type' => $revocationDirectInvitationReward,
                    'indirect' => [
                        Agent::LEVEL_GROUP_OWNER => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                        Agent::LEVEL_ELITE => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                        Agent::LEVEL_STRONGMAN => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                    ]
                ],
                Agent::LEVEL_STRONGMAN => [
                    'amount' => $directInviterReward,
                    'type' => $revocationDirectInvitationReward,
                    'indirect' => [
                        Agent::LEVEL_GROUP_OWNER => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                        Agent::LEVEL_ELITE => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                        Agent::LEVEL_STRONGMAN => ['amount' => $indirectInviterReward, 'type' => $revocationIndirectInvitationReward],
                    ]
                ]
            ],
        ];
        if ($this->directInviter) {
            $rewardSetting = $levelGradeDifferenceReward[$this->agentSnapshot['level']][$this->directInviterSnapshot['level']]; // 邀请奖励配置
            $rewardAmountDetail = $rewardSetting['amount']; // 邀请奖励具体金额数量
            $this->directInviter->incrementOrDecrementBalance(
                $rewardAmountDetail['total'], // 所有 sku 奖励总和
                $rewardSetting['type'],
                $this->order,
                $method,
                $this->orderCreatedAt
            );
            // SKU 佣金数量统计
            foreach ($rewardAmountDetail['sku_details'] as $skuId => $skuDetail) {
                if ($rewardSetting['type'] === $typeRevocationCommission) {
                    // [统计] SKU 佣金
                    $this->commodityActivitySkuStatistics[$skuId]
                        ->incrementOrDecrementNumberOfCommissions(
                            $skuDetail['quantity'],
                            $skuDetail['unit_price'],
                            sprintf('number_of_%s_with_%s_commissions', $rewardSetting['from'], $rewardSetting['to']),
                            $method);
                } else {
                    // [统计] SKU 邀请奖励
                    $this->commodityActivitySkuStatistics[$skuId]
                        ->incrementOrDecrementNumberOfInvitationRewards($skuDetail['quantity'], $skuDetail['unit_price'], 'direct', $method);
                }
            }
            // 团队业绩
            $this->directInviter->incrementOrDecrementTeamPerformance($orderAmount, $method, $this->orderCreatedAt, $this->needDeductionOrder ? 1 : 0); // 订单失效的情况下扣减订单数
            // 团队收入
            $this->directInviter->incrementOrDecrementTeamIncome($totalIncome, $method, $this->orderCreatedAt);
            // 当整个订单失效时 退回培养奖
            $cultivationAward = 0;
            if ($this->needDeductionOrder
                && $this->agentSnapshot['cultivation_award'] === Agent::CULTIVATION_AWARD_OPEN
                && $this->agentSnapshot['level'] === Agent::LEVEL_STRONGMAN
                && $this->directInviterSnapshot['level'] === Agent::LEVEL_STRONGMAN) {

                $cultivationAward = Agent::CULTIVATION_AWARD;
                $this->directInviter->incrementOrDecrementBalance($cultivationAward, AgentRevenue::TYPE_REVOCATION_CULTIVATE_REWARDS, $this->order, 'decrement', $this->orderCreatedAt);
                // 培养奖统计
                $commodityActivityStatistics->incrementOrDecrementCultivationAwards();
            }

            // 团队订单关联
            $commission = 0;
            $reward = 0;
            // 佣金还是奖励
            if ($rewardSetting['type'] === $typeRevocationCommission) {
                $commission = $rewardAmountDetail['total'];
            } else {
                $reward = $rewardAmountDetail['total'];
            }
            // 直接邀请人对于此订单获得奖励相关的统计
            if ($commission > 0 || $reward > 0) {
                $this->directInviter
                    ->relatedOrders()
                    ->wherePivot('type', Agent::AGENT_ORDER_IDENTITY_TEAM)
                    ->updateExistingPivot($this->order['id'], [
                        'reward_summary' => \DB::raw('reward_summary - ' . $reward), // 奖励
                        'commission_summary' => \DB::raw('commission_summary - ' . $commission), // 佣金
                        'cultivation_awards_summary' => \DB::raw('cultivation_awards_summary - ' . $cultivationAward), // 培养奖
                    ]);
            }
        }

        if ($this->indirectInviter) {
            $rewardSetting = $levelGradeDifferenceReward[$this->agentSnapshot['level']][$this->directInviterSnapshot['level']]['indirect'][$this->indirectInviterSnapshot['level']]; // 邀请奖励配置
            $rewardAmountDetail = $rewardSetting['amount']; // 邀请奖励具体金额数量
            $this->indirectInviter->incrementOrDecrementBalance(
                $rewardAmountDetail['total'],
                $rewardSetting['type'],
                $this->order,
                $method,
                $this->orderCreatedAt
            );
            foreach ($rewardAmountDetail['sku_details'] as $commodityActivitySkuId => $skuDetail) {
                if ($rewardSetting['type'] === $typeRevocationCommission) {
                    // [统计] SKU 佣金
                    $this->commodityActivitySkuStatistics[$commodityActivitySkuId]
                        ->incrementOrDecrementNumberOfCommissions(
                            $skuDetail['quantity'],
                            $skuDetail['unit_price'],
                            sprintf('number_of_%s_with_%s_commissions', $rewardSetting['from'], $rewardSetting['to']),
                            $method);
                } else {
                    // [统计] SKU 邀请奖励
                    $this->commodityActivitySkuStatistics[$commodityActivitySkuId]
                        ->incrementOrDecrementNumberOfInvitationRewards(
                            $skuDetail['quantity'],
                            $skuDetail['unit_price'],
                            'indirect',
                            $method);
                }
            }
            // 团队业绩
            $this->indirectInviter->incrementOrDecrementTeamPerformance($orderAmount, $method, $this->orderCreatedAt, $this->needDeductionOrder ? 1 : 0);
            // 团队收入
            $this->indirectInviter->incrementOrDecrementTeamIncome($totalIncome, $method, $this->orderCreatedAt);

            // 团队订单关联
            $commission = 0;
            $reward = 0;
            // 佣金还是奖励
            if ($rewardSetting['type'] === $typeRevocationCommission) {
                $commission = $rewardAmountDetail['total'];
            } else {
                $reward = $rewardAmountDetail['total'];
            }
            if ($commission > 0 || $reward > 0) {
                $this->indirectInviter
                    ->relatedOrders()
                    ->wherePivot('type', Agent::AGENT_ORDER_IDENTITY_TEAM)
                    ->updateExistingPivot($this->order['id'], [
                        'reward_summary' => \DB::raw('reward_summary - ' . $reward), // 奖励
                        'commission_summary' => \DB::raw('commission_summary - ' . $commission), // 佣金
                    ]);
            }
        }
    }

    /**
     * 计算订单是否退完了
     * @return bool
     */
    private function isOrderRetired()
    {
        // 统计已经通过售后的 sku_id => 数量
        $afterSaleOrderSku = [];
        $this->order->afterSaleOrder->each(function ($afterOrder) use (&$afterSaleOrderSku) {
            $afterOrder->afterSaleOrderSkus->each(function ($sku) use (&$afterSaleOrderSku) {
                $afterSaleOrderSku[$sku['commodity_activity_sku_id']] = ($afterSaleOrderSku[$sku['commodity_activity_sku_id']] ?? 0) + $sku['amount'];
            });
        });
        $isOrderRetired = true;
        // 原有订单的 SKU > 已经通过售后的 SKU + 提交的 SKU 数量, 说明还没有退完
        foreach ($this->order->skus as $sku) {
            // 订单的 SKU 数量 <= 售后的数量 + 提交的数量
            if ($sku['amount'] >= (($afterSaleOrderSku[$sku['commodity_activity_sku_id']] ?? 0) + ($this->skuWithQuantity[$sku['commodity_activity_sku_id']] ?? 0))) {
                $isOrderRetired = false;
                break;
            }
        }

        return $isOrderRetired;
    }
}
